/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Mcu_Vd.c                                                                           *
 * \brief    AUTOSAR 4.3.1 MCAL Mcu Driver                                                              *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2023/08/29     <td>1.0U.0U                                                                   *
 * </table>                                                                                             *
 *******************************************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#if defined (CFG_PLATFORM_MCAL)
#include "__regs_base.h"
#include "RegHelper.h"
#include "McuExt_Types.h"
#include "McuExt_Cfg.h"
#endif /** #if defined (CFG_PLATFORM_MCAL) */
#include "Vd.h"
/********************************************************************************************************
 *                                 Private Macro definition                                             *
 *******************************************************************************************************/
#define VD_FUNCTION_VIN0_OV_OFFSET                              (4U)
#define VD_FUNCTION_VIN1_OV_OFFSET                              (2U)
#define VD_FUNCTION_VIN2_OV_OFFSET                              (2U)
#define VD_FUNCTION_VIN3_OV_OFFSET                              (4U)
#define VD_FUNCTION_VIN0_UV_OFFSET                              (-4)
#define VD_FUNCTION_VIN1_UV_OFFSET                              (-2)
#define VD_FUNCTION_VIN2_UV_OFFSET                              (-2)
#define VD_FUNCTION_VIN3_UV_OFFSET                              (-4)
/* VD_SF VIN[0-3] ov and uv threshold trim value */
#define EFUSE_IP_ANALOG_VD_TRIM1_REG                            (0x1314U)
#define EFUSE_IP_ANALOG_VD_TRIM1_REG_EN_MASK                    (24U)
#define EFUSE_IP_ANALOG_VD_TRIM1_REG_VIN_EN_MASK                (31U)
/* VD_LP VIN[0-3] ov and uv threshold trim value */
#define EFUSE_IP_ANALOG_VD_TRIM2_REG                            (0x105CU)
#define EFUSE_IP_ANALOG_VD_TRIM2_REG_EN_MASK                    (24U)
/* VIN[0] trim value */
#define EFUSE_IP_ANALOG_VD_TRIM3_REG                            (0x1308U)
/********************************************************************************************************
 *                                  Private Variable Definitions                                        *
 *******************************************************************************************************/
#if defined (CFG_PLATFORM_MCAL)
#define MCUEXT_START_SEC_CONFIG_DATA_UNSPECIFIED
#include "McuExt_MemMap.h"
#endif /** #if defined (CFG_PLATFORM_MCAL) */
/*PRQA S 3218 1*/
static const Vd_TrimConfigType Vd_TrimConfigTable[] =
{   /* efuseValue */    /* offset */    /* upperLimit */     /* lowLimit */
    {0x00U,              0,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x01U,              1,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x02U,              2,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x03U,              3,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x04U,              0,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x05U,             -3,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x06U,             -2,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
    {0x07U,             -1,             VD_THRESHOLD_MAX,   VD_THRESHOLD_MIN},
};
#if defined (CFG_PLATFORM_MCAL)
#define MCUEXT_STOP_SEC_CONFIG_DATA_UNSPECIFIED
#include "McuExt_MemMap.h"
#endif /** #if defined (CFG_PLATFORM_MCAL) */
/********************************************************************************************************
 *                                  Private Function Declarations                                       *
 *******************************************************************************************************/
/*PRQA S 3673 1*/
#if defined (CFG_PLATFORM_MCAL)
#define MCUEXT_START_SEC_CODE
#include "McuExt_MemMap.h"
#endif /** #if defined (CFG_PLATFORM_MCAL) */
/* PRQA S 3206 30 */
/** **************************************************************************************
 * \brief This function is service to clear VD interrupt state

 * \verbatim
 * Syntax             : void Vd_ClrIntState(uint32_t baseAddress, uint32_t intStateEnable,
                            uint32_t safetyIntStateEnable)
 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : baseAddress          - Controller base address
                        intStateEnable       - VD interrupt enabled bits
                        safetyIntStateEnable - VD safety interrupt enabled bits

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : VD_E_OK - Read vd fuse complete
 *                      E_NOT_OK - Read vd fuse did not complete

 * Description        : This function is service to clear VD interrupt state

 * \endverbatim
 * Traceability       :
 *****************************************************************************************/
static void Vd_ClrIntState(uint32_t baseAddress, uint32_t intStateEnable,
        uint32_t safetyIntStateEnable)
{
    uint32_t funcStat;

    VdHookBegin_Vd_ClrIntState(baseAddress);

    /* #10 read FUNC_STAT_OFF*/
    funcStat = readl(baseAddress + FUNC_STAT_OFF);

    /* #20 setting FUNC_STAT_EN and FUNC_INT_SIG_EN to '0x0'*/
    writel(0U, baseAddress + FUNC_STAT_EN_OFF);

    if (intStateEnable != 0U)
    {
        writel(0U, baseAddress + FUNC_INT_SIG_EN_OFF);
    } /* else not needed */

#if VD_SAFETY_INTERRUPT_ENABLE
    writel(0U, baseAddress + FUNC_UNC_SIG_EN_OFF);
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */

    /* #40 setting FUNC_STAT_CLR_OFF to 1*/
    writel(funcStat, baseAddress + FUNC_STAT_CLR_OFF);
    /* #50 setting FUNC_STAT_EN and FUNC_STAT_EN_OFF to '0x1'*/
    writel(0xFFFFU, baseAddress + FUNC_STAT_EN_OFF);

    /* #100 Enable interrupts */
    if (intStateEnable != 0U)
    {
        writel(intStateEnable, baseAddress + FUNC_INT_SIG_EN_OFF);
    } /* else not needed */

#if VD_SAFETY_INTERRUPT_ENABLE

    /* #110 Enable safety interrupts */
    writel(safetyIntStateEnable, baseAddress + FUNC_UNC_SIG_EN_OFF);

#endif /* #if VD_SAFETY_INTERRUPT_ENABLE */

}

/** **************************************************************************************
 * \brief This function is service to calculate trim threshold

 * \verbatim
 * Syntax             : uint8_t Vd_TrimThresholdCalculate(uint8_t VdThreshold, int8_t efuseValue)
 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : VdThreshold - VD threshold value
                        efuseValue  - efuse value

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : uint8_t - VD threshold value after trim

 * Description        : This function is service to calculate trim threshold

 * \endverbatim
 * Traceability       :
 *****************************************************************************************/
static uint8_t Vd_TrimThresholdCalculate(uint8_t VdThreshold, uint32_t efuseValue)
{
    uint8_t index;
    uint8_t temp;
    int16_t errorTemp;
    int16_t warnTemp;
    int16_t vdTrimOffset = 0;
    uint8_t vdThresholdAfterTrim;

    /* Loop find trim offset */
    for (index = 0U; index < (sizeof(Vd_TrimConfigTable)/sizeof(Vd_TrimConfigTable[0U])); index++)
    {
        if (efuseValue == Vd_TrimConfigTable[index].efuseValue)
        {
            vdTrimOffset = Vd_TrimConfigTable[index].offset;
            break;
        }
    }

    /* Calculate error threshold */
    temp = (VdThreshold >> VD_ERRTHRESHOLD_OFFSET);
    errorTemp = (int16_t)temp + (int16_t)vdTrimOffset;

    /* Calculate warning threshold */
    temp = (VdThreshold & VD_WARNINGTHRESHOLD_MASK);
    warnTemp = (int16_t)temp + (int16_t)vdTrimOffset;

    VdHookBegin_Vd_TrimThresholdCalculate();

    /* Check upper and low limitation */
    if (errorTemp > (int16_t)VD_THRESHOLD_MAX)
    {
        errorTemp = (int16_t)VD_THRESHOLD_MAX;
    }

    if (errorTemp < (int16_t)VD_THRESHOLD_MIN)
    {
        errorTemp = (int16_t)VD_THRESHOLD_MIN;
    }



    /* Check upper and low limitation */
    if (warnTemp > (int16_t)VD_THRESHOLD_MAX)
    {
        warnTemp = (int16_t)VD_THRESHOLD_MAX;
    }

    if (warnTemp < (int16_t)VD_THRESHOLD_MIN)
    {
        warnTemp = (int16_t)VD_THRESHOLD_MIN;
    }

    /*PRQA S 4393,4533 1*/
    vdThresholdAfterTrim = (uint8_t)((errorTemp << VD_ERRTHRESHOLD_OFFSET) + warnTemp);

    return vdThresholdAfterTrim;
}
/** **************************************************************************************
 * \brief This function is service to calucate VD vin select threshold

 * \verbatim
 * Syntax             : static void Vd_VinsetThresholdMap(McuExt_VdCfgType *vdCfgPtrAux)
 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : vdCfgPtr     - Pointer to VD configuration
                        vdCfgPtrAux  - Pointer to VD aux configuration

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : None

 * Description        : This function is service to calucate VD vin select threshold

 * \endverbatim
 * Traceability       :
 *****************************************************************************************/
/*PRQA S 3673 1*/
static void Vd_VinsetThresholdMap(McuExt_VdCfgType *vdCfgPtrAux)
{
    uint32_t vdTrimEnable;
    uint32_t vdTrimValue;
    uint32_t vin0TrimValue;
    uint8_t vin0TrimThreshold;
    uint32_t voltSetEn;

    /* #10 Gets the bits of whether analog trim is complete */
    vdTrimValue = readl(APB_EFUSEC_BASE + EFUSE_IP_ANALOG_VD_TRIM1_REG);
    voltSetEn = (vdTrimValue >> EFUSE_IP_ANALOG_VD_TRIM1_REG_VIN_EN_MASK) & 0x01U;
    if (MCUEXT_APB_VD_SF_BASE == vdCfgPtrAux->base)
    {
        vdTrimEnable = (vdTrimValue >> EFUSE_IP_ANALOG_VD_TRIM1_REG_EN_MASK) & 0x01U;
    }
    else /* (MCUEXT_APB_VD_LP_BASE == vdCfgPtrAux->base) */
    {
        vdTrimValue = readl(APB_EFUSEC_BASE + EFUSE_IP_ANALOG_VD_TRIM2_REG);
        vdTrimEnable = (vdTrimValue >> EFUSE_IP_ANALOG_VD_TRIM2_REG_EN_MASK) & 0x01U;
    }

    VdHookBegin_Vd_VinsetThresholdMap();

    if (0x01U == vdTrimEnable)
    {
        /* Calibration all ov and uv threshold */
        vdCfgPtrAux->ovThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->ovThreshold.vin0Threshold, ((vdTrimValue >> 0U) & 0x07U));
        vdCfgPtrAux->ovThreshold.vin1Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->ovThreshold.vin1Threshold, ((vdTrimValue >> 3U) & 0x07U));
        vdCfgPtrAux->ovThreshold.vin2Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->ovThreshold.vin2Threshold, ((vdTrimValue >> 6U) & 0x07U));
        vdCfgPtrAux->ovThreshold.vin3Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->ovThreshold.vin3Threshold, ((vdTrimValue >> 9U) & 0x07U));
        vdCfgPtrAux->uvThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->uvThreshold.vin0Threshold, ((vdTrimValue >> 12U) & 0x07U));
        vdCfgPtrAux->uvThreshold.vin1Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->uvThreshold.vin1Threshold, ((vdTrimValue >> 15U) & 0x07U));
        vdCfgPtrAux->uvThreshold.vin2Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->uvThreshold.vin2Threshold, ((vdTrimValue >> 18U) & 0x07U));
        vdCfgPtrAux->uvThreshold.vin3Threshold = Vd_TrimThresholdCalculate(vdCfgPtrAux->uvThreshold.vin3Threshold, ((vdTrimValue >> 21U) & 0x07U));
    }

    VdHookBegin_Vd_VinsetThresholdMap();

    if (0x01U == voltSetEn)
    {
        /* Read VD SF/LP VIN[0] from efuse */
        vin0TrimValue = readl(APB_EFUSEC_BASE + EFUSE_IP_ANALOG_VD_TRIM3_REG);

        if (MCUEXT_APB_VD_SF_BASE == vdCfgPtrAux->base)
        {
            /* The supply voltage is 0.8V */
            vdCfgPtrAux->voltageSelect.vin0Select = (uint8_t)(((vin0TrimValue >> 8U) & 0x3FU) | 0x40U);
            vin0TrimThreshold = (uint8_t)(vin0TrimValue & 0x0FU);
            vin0TrimThreshold = (vin0TrimThreshold << 4U) | vin0TrimThreshold;
            vdCfgPtrAux->ovThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vin0TrimThreshold, ((vdTrimValue >> 0U) & 0x07U));
            vin0TrimThreshold = (uint8_t)((vin0TrimValue >> 4U) & 0x0FU);
            vin0TrimThreshold = (vin0TrimThreshold << 4U) | vin0TrimThreshold;
            vdCfgPtrAux->uvThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vin0TrimThreshold, ((vdTrimValue >> 12U) & 0x07U));
        }
        else /* (MCUEXT_APB_VD_LP_BASE == vdCfgPtrAux->base) */
        {
            vin0TrimThreshold = (uint8_t)((vin0TrimValue >> 20U) & 0x0FU);
            vin0TrimThreshold = (vin0TrimThreshold << 4U) | vin0TrimThreshold;
            vdCfgPtrAux->ovThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vin0TrimThreshold, ((vdTrimValue >> 0U) & 0x07U));

#if VD_ND_MODE
            vin0TrimThreshold = (uint8_t)((vin0TrimValue >> 28U) & 0x0FU);
            vin0TrimThreshold = (vin0TrimThreshold << 4U) | vin0TrimThreshold;
            vdCfgPtrAux->uvThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vin0TrimThreshold, ((vdTrimValue >> 12U) & 0x07U));

            vin0TrimValue = readl(APB_EFUSEC_BASE + EFUSE_IP_ANALOG_VD_TRIM3_REG + 4U);
            vdCfgPtrAux->voltageSelect.vin0Select = (uint8_t)(((vin0TrimValue >> 0U) & 0x3FU) | 0x40U);
#else
            vdCfgPtrAux->voltageSelect.vin0Select = (uint8_t)(((vin0TrimValue >> 14U) & 0x3FU) | 0x40U);
            vin0TrimThreshold = (uint8_t)((vin0TrimValue >> 24U) & 0x0FU);
            vin0TrimThreshold = (vin0TrimThreshold << 4U) | vin0TrimThreshold;
            vdCfgPtrAux->uvThreshold.vin0Threshold = Vd_TrimThresholdCalculate(vin0TrimThreshold, ((vdTrimValue >> 12U) & 0x07U));
#endif /* VD_OD_MODE */
        }
    }

    VdHookEnd_Vd_VinsetThresholdMap(vdCfgPtrAux->base);

}

#if VD_SAFETY_INTERRUPT_ENABLE
/** **************************************************************************************
 * \brief This function is service to VD error injection

 * \verbatim
 * Syntax             : lld_status_t Vd_ErrorInjection(const McuExt_VdCfgType *localVdConfig)
 *
 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : vdCfgPtr     - Pointer to VD configuration
                        vdCfgPtrAux  - Pointer to VD aux configuration

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : None

 * Description        : This function is service to VD error injection. For verifer
                        safety mechansim

 * \endverbatim
 * Traceability       :
 *****************************************************************************************/
static lld_status_t Vd_ErrorInjection(const McuExt_VdCfgType *localVdConfig)
{
    lld_status_t errorId = VD_E_OK;
    uint32_t regValue;

    /* Clear functional interrupt status */
    writel(0xFFFFU, localVdConfig->base + FUNC_STAT_CLR_OFF);
    /* Enable functional interrupt status */
    writel(0xFFFFU, localVdConfig->base + FUNC_STAT_EN_OFF);

    /* Error injection set over voltage threshold */
    writel(0U, localVdConfig->base + CFG_OV_THRE_OFF(0U));
    /* Error injection set under voltage threshold */
    writel(0U, localVdConfig->base + CFG_UV_THRE_OFF(0U));

    /* #70 Wait 8 us, waiting for analog output stable */
    (void)VD_UDELAY(8U);

    /* Get functional interrupt status */
    regValue = readl(localVdConfig->base + FUNC_STAT_OFF);

    VdHookBegin_Vd_ErrorInjection();

    if (regValue != 0xFFFFU)
    {
        errorId = VD_E_ERROR_INJECT_FAILED;
    } /* else not needed */

    /* Disable all functional interrupt status */
    writel(0x0U, localVdConfig->base + FUNC_STAT_EN_OFF);
    /* Clear functional interrupt status */
    writel(0xFFFFU, localVdConfig->base + FUNC_STAT_CLR_OFF);

    return errorId;
}
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */
/********************************************************************************************************
 *                                  Global Function Declarations                                        *
 *******************************************************************************************************/

/*PRQA S 3673 29*/
/** **************************************************************************************
 * \brief This function is used to get vd interrupt status.

 * \verbatim
 * Syntax             : uint32_t Vd_GetInterruptStatus(const McuExt_VdControllerType *localVdCfgPtr)

 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : vdCfgPtr - vd configuration pointer

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : uint32_t - vd interrupt status

 * Description        : Get vd interrupt status
 *

 * \endverbatim
 *
 * Traceability       : SWSR_MCU_048 SW_SM001 SW_SM006
 *****************************************************************************************/
uint32_t Vd_GetInterruptStatus(const McuExt_VdControllerType *localVdCfgPtr)
{
    /* ----- Local Variables ---------------------------------------------- */
    /* Variable used to store current error status */
    uint32_t retVal;

    /* ----- Implementation ----------------------------------------------- */
    /* #20 Reads the status of the VD int register*/
    retVal = readl(localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_OFF);

    return retVal;
}

/*PRQA S 3673 28*/
/** **************************************************************************************
 * \brief This function is used to get vd dynamic status.

 * \verbatim
 * Syntax             : uint32_t Vd_GetDynamicStatus(const McuExt_VdControllerType *localVdCfgPtr)

 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : vdCfgPtr - vd configuration pointer

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : uint32_t - vd dynamic status

 * Description        : Get vd dynamic status
 *

 * \endverbatim
 * Traceability       : SWSR_MCU_048 SW_SM001 SW_SM006
 *****************************************************************************************/
uint32_t Vd_GetDynamicStatus(const McuExt_VdControllerType *localVdCfgPtr)
{
    /* ----- Local Variables ---------------------------------------------- */
    /* Variable used to store current error status */
    uint32_t retVal;

    /* ----- Implementation ----------------------------------------------- */
    /* #20 Reads the status of the VD dynamic register*/
    retVal = readl(localVdCfgPtr->vdCfgPtr->base + FUNC_DY_STAT_OFF);

    return retVal;
}

/** **************************************************************************************
 * \brief This function is used to clear vd interrupt status.

 * \verbatim
 * Syntax             : void Vd_ClearInterruptStatus(const McuExt_VdControllerType *localVdCfgPtr)

 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : vdCfgPtr - vd configuration pointer

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : None

 * Description        : Clear vd interrupt status
 *

 * \endverbatim
 * Traceability       : SWSR_MCU_048 SW_SM001 SW_SM006
 *****************************************************************************************/
void Vd_ClearInterruptStatus(const McuExt_VdControllerType *localVdCfgPtr)
{
    /* ----- Local Variables ---------------------------------------------- */
    /* Variable used to store current error status */

    /* ----- Implementation ----------------------------------------------- */
    /*#20 Vd clear int States*/
    Vd_ClrIntState(localVdCfgPtr->vdCfgPtr->base, localVdCfgPtr->vdCfgPtr->intStaEn,
                                    localVdCfgPtr->vdCfgPtr->safetyIntStaEn);
}

/** **************************************************************************************
 * \brief This function is used to initialize voltage detector.

 * \verbatim
 * Syntax             : lld_status_t Vd_Init(McuExt_VdControllerType *localVdCfgPtr,
 *                                            const McuExt_VdCfgType *vdCfgPtr)
 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : vdCfgPtr - vd configuration pointer

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : VD_E_OK - Initialize voltage detector successfully
 *                      E_NOT_OK - Initialize voltage detector unsuccessfully

 * Description        : Initialize voltage detector
 *

 * \endverbatim
 * Traceability       : SWSR_MCU_048 SW_SM001 SW_SM006
 *****************************************************************************************/
lld_status_t Vd_Init(McuExt_VdControllerType *localVdCfgPtr, const McuExt_VdCfgType *vdCfgPtr)
{
    /* ----- Local Variables ---------------------------------------------- */
    /* Variable used to store current error status */
    lld_status_t errorId;
    McuExt_VdCfgType localVdConfig;
    uint32_t funcStat;
    uint32_t analogStat;
    uint32_t vinsetVal;
    uint32_t ovThreVal;
    uint32_t uvThreVal;
    uint32_t cfgFiltVal;

    /* ----- Implementation ----------------------------------------------- */
    /*PRQA S 0314 1*/
    (void)VD_MEM_COPY((void *)&localVdConfig, (const void*)vdCfgPtr, sizeof(McuExt_VdCfgType));
    /* #10 set vd vinset and threshold map */
    Vd_VinsetThresholdMap(&localVdConfig);

    /* #30 set VOLT_SEL_OFF(0U) */
    vinsetVal = FV_VOLT_SEL_VD_VIN3_SEL(localVdConfig.voltageSelect.vin3Select) |
                FV_VOLT_SEL_VD_VIN2_SEL(localVdConfig.voltageSelect.vin2Select) |
                FV_VOLT_SEL_VD_VIN1_SEL(localVdConfig.voltageSelect.vin1Select) |
                FV_VOLT_SEL_VD_VIN0_SEL(localVdConfig.voltageSelect.vin0Select);
    writel(vinsetVal, localVdConfig.base + VOLT_SEL_OFF(0U));

#if VD_SAFETY_INTERRUPT_ENABLE

    if (localVdConfig.safetyIntStaEn != 0U)
    {
        errorId = Vd_ErrorInjection(vdCfgPtr);
    }
    else
    {
        errorId = VD_E_OK;
    }

    if (errorId == VD_E_OK)
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */
    {
        /* #40 set OV_THRE */
        ovThreVal = FV_CFG_OV_THRE_VD_VIN3_OV_TH(localVdConfig.ovThreshold.vin3Threshold) |
                    FV_CFG_OV_THRE_VD_VIN2_OV_TH(localVdConfig.ovThreshold.vin2Threshold) |
                    FV_CFG_OV_THRE_VD_VIN1_OV_TH(localVdConfig.ovThreshold.vin1Threshold) |
                    FV_CFG_OV_THRE_VD_VIN0_OV_TH(localVdConfig.ovThreshold.vin0Threshold);
        writel(ovThreVal, localVdConfig.base + CFG_OV_THRE_OFF(0U));

        /* #50 set UV_THRE */
        uvThreVal = FV_CFG_UV_THRE_VD_VIN3_UV_TH(localVdConfig.uvThreshold.vin3Threshold) |
                    FV_CFG_UV_THRE_VD_VIN2_UV_TH(localVdConfig.uvThreshold.vin2Threshold) |
                    FV_CFG_UV_THRE_VD_VIN1_UV_TH(localVdConfig.uvThreshold.vin1Threshold) |
                    FV_CFG_UV_THRE_VD_VIN0_UV_TH(localVdConfig.uvThreshold.vin0Threshold);

        writel(uvThreVal, localVdConfig.base + CFG_UV_THRE_OFF(0U));

        /* #60 set filter*/
        cfgFiltVal = FV_CFG_FILT_CFG_FFB(localVdConfig.filterConfig.configFallingFilterBandwidth) |
                     FV_CFG_FILT_CFG_RFB(localVdConfig.filterConfig.configRisingFilterBandwidth)  |
                     FV_CFG_FILT_CFG_SI(localVdConfig.filterConfig.configSampleInterval)          |
                     BM_CFG_FILT_CFG_EN;

        writel(cfgFiltVal, localVdConfig.base + CFG_FILT_OFF);

        /* #70 Wait 20 us, waiting for analog output stable */
        (void)VD_UDELAY(20U);

        /* #80 setting FUNC_STAT_CLR_OFF to 1, clear status*/
        writel(0xFFFFU, localVdConfig.base + FUNC_STAT_EN_OFF);
        funcStat = readl(localVdConfig.base + FUNC_STAT_OFF);
        writel(0U, localVdConfig.base + FUNC_STAT_EN_OFF);
        writel(funcStat, localVdConfig.base + FUNC_STAT_CLR_OFF);
        writel(0xFFFFU, localVdConfig.base + FUNC_STAT_EN_OFF);

        funcStat = readl(localVdConfig.base + FUNC_STAT_OFF);
        analogStat = readl(localVdConfig.base + ANA_STAT_DEBUG_OFF);

        VdHookBegin_Vd_Init();

        if ((funcStat | analogStat) != 0U)
        {
            errorId = VD_E_ATE_ANALOG_TRIM_FAIL;
        }
        else
        {
            errorId = VD_E_OK;
        }

        if (VD_E_OK == errorId)
        {
            if (localVdConfig.intStaEn != 0U)
            {
                writel(localVdConfig.intStaEn, localVdConfig.base + FUNC_INT_SIG_EN_OFF);
            } /* else not needed */

#if VD_SAFETY_INTERRUPT_ENABLE

            /* #110 Enable safety interrupts */
            if (localVdConfig.safetyIntStaEn != 0U)
            {
                writel(localVdConfig.safetyIntStaEn, localVdConfig.base + FUNC_UNC_SIG_EN_OFF);
            } /* else not needed */

#endif /* #if VD_SAFETY_INTERRUPT_ENABLE */

            localVdCfgPtr->vdCfgPtr = vdCfgPtr;
            localVdCfgPtr->vdStatus = VD_INIT;
        } /* else not needed */
    } /* else not needed */

    return errorId;
}

/** **************************************************************************************
 * \brief This function is service to handle vd interrupt.

 * \verbatim
 * Syntax             : void Vd_SFIrqHandler(const McuExt_VdControllerType *localVdCfgPtr)

 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : None

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : None

 * Description        : This function is service to handle vd interrupt.
 *
 * \endverbatim
 * Traceability       :
 *****************************************************************************************/
void Vd_SFIrqHandler(const McuExt_VdControllerType *localVdCfgPtr)
{
    uint32_t intStatus;
    uint32_t intEnable;

    if (VD_UNINIT == localVdCfgPtr->vdStatus)
    {
        /* #10 If vd has been uninitialized, clear all interrupt status and disable all interrupt */
        writel(0U, MCUEXT_APB_VD_SF_BASE + FUNC_STAT_EN_OFF);
        writel(0U, MCUEXT_APB_VD_SF_BASE + FUNC_INT_SIG_EN_OFF);
        writel(0xFFFFFFFFU, MCUEXT_APB_VD_SF_BASE + FUNC_STAT_CLR_OFF);
#if VD_SAFETY_INTERRUPT_ENABLE
        writel(0U, MCUEXT_APB_VD_SF_BASE + FUNC_UNC_SIG_EN_OFF);
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */
    }
    else
    {
        /* #20 If vd has been initialized, read interrupt status and interrupt enable value */
        intStatus = readl(localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_OFF);
        intEnable = readl(localVdCfgPtr->vdCfgPtr->base + FUNC_INT_SIG_EN_OFF);

        VdHookBegin_Vd_IrqHandlerPhase0();
        /* #30 If interrupt status is not enabled, clear interrupt status and disable interrupt */
        if (0U == (intStatus & intEnable))
        {
            writel(0U, localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_EN_OFF);
            writel(0U, localVdCfgPtr->vdCfgPtr->base + FUNC_INT_SIG_EN_OFF);
            writel(0xFFFFFFFFU, localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_CLR_OFF);
#if VD_SAFETY_INTERRUPT_ENABLE
            writel(0U, MCUEXT_APB_VD_SF_BASE + FUNC_UNC_SIG_EN_OFF);
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */
        }
        else
        {
            /* #40 If interrupt status is enabled, clear interrupt status */
            Vd_ClrIntState(localVdCfgPtr->vdCfgPtr->base, localVdCfgPtr->vdCfgPtr->intStaEn, localVdCfgPtr->vdCfgPtr->safetyIntStaEn);
#if VD_ENABLE_NOTIFICATION_API
            /* #50 Call vd notification function */
            if (localVdCfgPtr->vdCfgPtr->vdNotificationPtr != NULL)
            {
                localVdCfgPtr->vdCfgPtr->vdNotificationPtr(intStatus);
            } /* else not needed */
#endif /** #if VD_ENABLE_NOTIFICATION_API */
        }
    }
}

/** **************************************************************************************
 * \brief This function is service to handle vd interrupt.

 * \verbatim
 * Syntax             : void Vd_LPIrqHandler(const McuExt_VdControllerType *localVdCfgPtr)

 * Service ID[hex]    : None

 * Sync/Async         : Synchronous

 * Reentrancy         : Non reentrant

 * Parameters (in)    : None

 * Parameters (inout) : None

 * Parameters (out)   : None

 * Return value       : None

 * Description        : This function is service to handle vd interrupt.
 *
 * \endverbatim
 * Traceability       :
 *****************************************************************************************/
void Vd_LPIrqHandler(const McuExt_VdControllerType *localVdCfgPtr)
{
    uint32_t intStatus;
    uint32_t intEnable;

    if (VD_UNINIT == localVdCfgPtr->vdStatus)
    {
        /* #10 If vd has been uninitialized, clear all interrupt status and disable all interrupt */
        writel(0U, MCUEXT_APB_VD_LP_BASE + FUNC_STAT_EN_OFF);
        writel(0U, MCUEXT_APB_VD_LP_BASE + FUNC_INT_SIG_EN_OFF);
        writel(0xFFFFFFFFU, MCUEXT_APB_VD_LP_BASE + FUNC_STAT_CLR_OFF);
#if VD_SAFETY_INTERRUPT_ENABLE
        writel(0U, MCUEXT_APB_VD_LP_BASE + FUNC_UNC_SIG_EN_OFF);
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */
    }
    else
    {
        /* #20 If vd has been initialized, read interrupt status and interrupt enable value */
        intStatus = readl(localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_OFF);
        intEnable = readl(localVdCfgPtr->vdCfgPtr->base + FUNC_INT_SIG_EN_OFF);

        VdHookBegin_Vd_IrqHandlerPhase0();
        /* #30 If interrupt status is not enabled, clear interrupt status and disable interrupt */
        if (0U == (intStatus & intEnable))
        {
            writel(0U, localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_EN_OFF);
            writel(0U, localVdCfgPtr->vdCfgPtr->base + FUNC_INT_SIG_EN_OFF);
            writel(0xFFFFFFFFU, localVdCfgPtr->vdCfgPtr->base + FUNC_STAT_CLR_OFF);
#if VD_SAFETY_INTERRUPT_ENABLE
            writel(0U, MCUEXT_APB_VD_SF_BASE + FUNC_UNC_SIG_EN_OFF);
#endif /** #if VD_SAFETY_INTERRUPT_ENABLE */
        }
        else
        {
            /* #40 If interrupt status is enabled, clear interrupt status */
            Vd_ClrIntState(localVdCfgPtr->vdCfgPtr->base, localVdCfgPtr->vdCfgPtr->intStaEn, localVdCfgPtr->vdCfgPtr->safetyIntStaEn);
#if VD_ENABLE_NOTIFICATION_API
            /* #50 Call vd notification function */
            if (localVdCfgPtr->vdCfgPtr->vdNotificationPtr != NULL)
            {
                localVdCfgPtr->vdCfgPtr->vdNotificationPtr(intStatus);
            } /* else not needed */
#endif /** #if VD_ENABLE_NOTIFICATION_API */
        }
    }
}

#if defined (CFG_PLATFORM_MCAL)
#define MCUEXT_STOP_SEC_CODE
#include "McuExt_MemMap.h"
#endif /** #if defined (CFG_PLATFORM_MCAL) */

#ifdef __cplusplus
}
#endif
/* End of file */
